/**  
 * All rights Reserved, Designed By www.rrbzs.com
 * @Title:  AutoDeployApplication.java   
 * @Package com.rrb.appliation   
 * @Description:    TODO (用一句话描述该文件做什么)   
 * @author: daiw     
 * @date:   2022年4月1日 下午4:02:54   
 * @Copyright: 2022 rrbzs.com Inc. All rights reserved. 
 * 注意：本内容仅限于深圳人人帮科技有限公司内部传阅，禁止外泄以及用于其他的商业目
 */
package com.rrb.appliation;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cn.hutool.core.io.FileUtil;

/**
 * @ClassName: AutoDeployApplication
 * @Description: TODO (这里用一句话描述这个类的作用)
 * @author: daiw
 * @date: 2022年4月1日 下午4:02:54
 * 
 * @Copyright: 2022 www.rrbzs.com Inc. All rights reserved.
 *             注意：本内容仅限于深圳人人帮科技有限公司内部传阅，禁止外泄以及用于其他的商业目
 */
public class AutoDeployApplication {
	private static List<String> configDemo;
	private static Map<String, String> configs = new HashMap<>();
	private static List<String> CREATE_PROJECT_SHELL_CMDS;
	static {
		configDemo = new ArrayList<>();
		configDemo.add("#应用服务名称，eg：demo.jar为服务包，则appName=demo");
		configDemo.add("appName=demo");
		configDemo.add("#工程git地址");
		configDemo.add("gitRepository=https://");
		configDemo.add("#代码分支");
		configDemo.add("branch=master");
		configDemo.add("#工程包路径，上级目录是src");
		configDemo.add("jarPath=/demo");
		configDemo.add("#运行实例数量");
		configDemo.add("instanceCount=1");
		configDemo.add("#端口号，多个端口号用,号分隔");
		configDemo.add("port=8085");
		configDemo.add("end");

		CREATE_PROJECT_SHELL_CMDS = new ArrayList<>(2);
		CREATE_PROJECT_SHELL_CMDS.add("#!/bin/bash");
		CREATE_PROJECT_SHELL_CMDS.add("java -jar ./bin/auto-deploy.jar $1");

	}

	private static String projectAbsolutePath;

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		StringBuilder sb = new StringBuilder();
		sb.append("未知参数，请参照以下参数:")//
				.append("\r\n\t init-env 初始化基础环境")//
				.append("\r\n\t init-project 初始化工程环境")//
				.append("\r\n\t init-git-repo 初始化git库")//
				.append("\r\n\t start 启动服务")//
				.append("\r\n\t stop 停止服务")//
				.append("\r\n\t update 重新发布服务（确保deployPkg有新包）")//
				.append("\r\n\t compile 拉取、编译最新代码，拷贝到deployPkg")//
				.append("\r\n\t redeploy 拉取最新代码，重新发布服务")//
				.append("\r\n\t clear 清除deployPkg下的包")//
				.append("\r\n\t reinit-project 修改配置文件后，重新初始化工程");

		if (args == null || args.length == 0) {
			System.out.println(sb.toString());
			return;
		}

		// 获取工程绝对路径
		projectAbsolutePath = LinuxHelper.runCmdBackResult("pwd");

		// 初始化部署环境
		initConfig();

		// 初始化部署环境
		if (args[0].equals("init-env")) {
			if (FileUtil.exist(projectAbsolutePath + "/shomeedo.sh")) {
				System.out.println("无需重复初始化!");
				return;
			}
			// 1、创建代码目录 src，运行包目录 package，脚本目录 bin，日志目录 logs，更新包目录deployPkg
			LinuxHelper.runCmd("mkdir src package bin logs config deployPkg backup");
			// 2、初始化配置文件 autodeploy-config.properties
			String propertiesPath = projectAbsolutePath + "/config/autodeploy-config.properties";
			FileUtil.newFile(propertiesPath);
			FileUtil.writeLines(configDemo, propertiesPath, "UTF-8");
			// 3、初始化执行环境
			LinuxHelper.runCmd("cp ./auto-deploy.jar ./bin/auto-deploy.jar");
			LinuxHelper.runCmd("rm -rf " + projectAbsolutePath + "/auto-deploy.jar");
			String projectShell = projectAbsolutePath + "/shomeedo.sh";
			FileUtil.newFile(projectShell);
			FileUtil.writeLines(CREATE_PROJECT_SHELL_CMDS, projectShell, "UTF-8");
			LinuxHelper.runCmd("chmod +x shomeedo.sh");
			return;
		}

		if (args[0].equals("init-project")) {
			initProject();
			return;
		}

		if (args[0].equals("start")) {
			LinuxHelper.runCmd(projectAbsolutePath + "/bin/start.sh");
			return;
		}

		if (args[0].equals("stop")) {
			LinuxHelper.runCmd(projectAbsolutePath + "/bin/stop.sh");
			return;
		}

		if (args[0].equals("update")) {
			LinuxHelper.runCmd(projectAbsolutePath + "/bin/update.sh");
			return;
		}

		if (args[0].equals("compile")) {
			LinuxHelper.runCmd(projectAbsolutePath + "/bin/compile.sh");
			return;
		}

		if (args[0].equals("redeploy")) {
			LinuxHelper.runCmd(projectAbsolutePath + "/bin/redeploy.sh");
			return;
		}

		if (args[0].equals("init-git-repo")) {
			LinuxHelper.runCmd(projectAbsolutePath + "/bin/init-git-repo.sh");
			return;
		}

		if (args[0].equals("clear")) {
			LinuxHelper.runCmd(projectAbsolutePath + "/bin/clear.sh");
			return;
		}

		if (args[0].equals("reinit-project")) {
			LinuxHelper.runCmd("rm -rf " + projectAbsolutePath + "/bin/*");
			LinuxHelper.runCmd("rm -rf " + projectAbsolutePath + "/src/*");
			initProject();
			return;
		}
		System.out.println(sb.toString());
	}

	private static boolean initProject() {
		if (FileUtil.exist(projectAbsolutePath + "/src/start.sh")) {
			System.out.println("无需重复初始化!");
			return false;
		}
		createStopShell();
		createStartShell();
		createClearShell();
		createUpdateShell();
		createInitGitRepositoryShell();
		createCompileCodeShell();
		createRedeployShell();
		System.out.println("正在初始化git库...");
		LinuxHelper.runCmd(projectAbsolutePath + "/bin/init-git-repo.sh");
		System.out.println("拉取和编译最新代码...");
		LinuxHelper.runCmd(projectAbsolutePath + "/bin/compile.sh");
		return true;
	}

	private static void createRedeployShell() {
		String shellPath = projectAbsolutePath + "/bin/redeploy.sh";
		List<String> shellCmds = new ArrayList<>();
		shellCmds.add("#!/bin/bash");
		shellCmds.add(projectAbsolutePath + "/bin/compile.sh");
		shellCmds.add(projectAbsolutePath + "/bin/update.sh");
		FileUtil.newFile(shellPath);
		FileUtil.writeLines(shellCmds, shellPath, "UTF-8");
		LinuxHelper.runCmd("chmod +x " + shellPath);
	}

	private static void createCompileCodeShell() {
		String shellPath = projectAbsolutePath + "/bin/compile.sh";
		List<String> shellCmds = new ArrayList<>();
		shellCmds.add("#!/bin/bash");
		shellCmds.add("echo 获取最新代码");
		shellCmds.add("cd " + projectAbsolutePath + "/src");
		// 拉取最新代码
		shellCmds.add("git pull " + configs.get("gitRepository") + " " + configs.get("branch"));
		// 打包
		shellCmds.add("mvn package -Dmaven.test.skip=true");
		shellCmds.add("cp " + projectAbsolutePath + "/src" + configs.get("jarPath") + "/target/" + configs.get("appName") + ".jar " + projectAbsolutePath + "/deployPkg/");
		shellCmds.add("mvn clean");
		shellCmds.add("cd ..");

		FileUtil.newFile(shellPath);
		FileUtil.writeLines(shellCmds, shellPath, "UTF-8");
		LinuxHelper.runCmd("chmod +x " + shellPath);
	}

	private static void createInitGitRepositoryShell() {
		String shellPath = projectAbsolutePath + "/bin/init-git-repo.sh";
		List<String> shellCmds = new ArrayList<>();
		shellCmds.add("#!/bin/bash");
		shellCmds.add("echo 初始化本地git库");
		shellCmds.add("cd src");
		shellCmds.add("git init");
		shellCmds.add("git clone " + configs.get("gitRepository"));
		shellCmds.add("cd ..");
		FileUtil.newFile(shellPath);
		FileUtil.writeLines(shellCmds, shellPath, "UTF-8");
		LinuxHelper.runCmd("chmod +x " + shellPath);
	}

	private static void createUpdateShell() {
		String shellPath = projectAbsolutePath + "/bin/update.sh";
		List<String> shellCmds = new ArrayList<>();
		shellCmds.add("#!/bin/bash");
		shellCmds.add("echo 停止服务");
		shellCmds.add(projectAbsolutePath + "/bin/stop.sh");
		shellCmds.add("sleep 3s");
		shellCmds.add("echo 备份服务jar包");
		String appName = configs.get("appName") + ".jar";
		shellCmds.add("cp " + projectAbsolutePath + "/package/" + appName + " " + projectAbsolutePath + "/backup/" + appName + ".$(date \"+%Y%m%d%H%M%S\")");
		shellCmds.add("echo 删除旧服务包");
		shellCmds.add("rm -rf " + projectAbsolutePath + "/package/*.jar");
		shellCmds.add("echo 拷贝新服务包");
		shellCmds.add("cp " + projectAbsolutePath + "/deployPkg/*.jar " + projectAbsolutePath + "/package/");
		shellCmds.add("echo 启动新服务包...");
		shellCmds.add(projectAbsolutePath + "/bin/start.sh");
		shellCmds.add(projectAbsolutePath + "/bin/clear.sh");
		FileUtil.newFile(shellPath);
		FileUtil.writeLines(shellCmds, shellPath, "UTF-8");
		LinuxHelper.runCmd("chmod +x " + shellPath);
	}

	private static void createClearShell() {
		String shellPath = projectAbsolutePath + "/bin/clear.sh";
		List<String> shellCmds = new ArrayList<>();
		shellCmds.add("#!/bin/bash");
		StringBuilder sb = new StringBuilder();
		// rm -rf ./pkg/*.jar
		// echo 旧包清理完毕！
		sb.append("rm -rf ")//
				.append(projectAbsolutePath)//
				.append("/deployPkg/*.jar");
		shellCmds.add(sb.toString());
		shellCmds.add("echo 旧包清理完毕！");
		FileUtil.newFile(shellPath);
		FileUtil.writeLines(shellCmds, shellPath, "UTF-8");
		LinuxHelper.runCmd("chmod +x " + shellPath);
	}

	private static void createStartShell() {
		String shellPath = projectAbsolutePath + "/bin/start.sh";
		List<String> shellCmds = new ArrayList<>();
		shellCmds.add("#!/bin/bash");
		int instanceCount = Integer.parseInt(configs.get("instanceCount"));
		String[] ports = configs.get("port").split(",");
		for (int i = 0; i < instanceCount; i++) {
			StringBuilder sb = new StringBuilder();
			sb.append("nohup java -jar ")//
					.append(projectAbsolutePath)//
					.append("/package/").append(configs.get("appName"))//
					.append(".jar ")//
					.append("--server.name=")//
					.append(configs.get("appName"))//
					.append("-")//
					.append(ports[i])//
					.append(" --server.port=")//
					.append(ports[i])//
					.append(" > ./logs/")//
					.append(configs.get("appName"))//
					.append("-")//
					.append(ports[i])//
					.append(" 2>&1 &");
			shellCmds.add(sb.toString());
		}
		FileUtil.newFile(shellPath);
		FileUtil.writeLines(shellCmds, shellPath, "UTF-8");
		LinuxHelper.runCmd("chmod +x " + shellPath);
	}

	private static void createStopShell() {
		String stopShell = projectAbsolutePath + "/bin/stop.sh";
		List<String> createStopShellCmds = new ArrayList<>();
		createStopShellCmds.add("#!/bin/bash");
		createStopShellCmds.add("PID=$(ps -ef | grep " + configs.get("appName") + ".jar | grep -v grep | awk '{ print $2 }')");
		createStopShellCmds.add("if [ -z \"$PID\" ]");
		createStopShellCmds.add("then");
		createStopShellCmds.add("    echo " + configs.get("appName") + " is already stopped");
		createStopShellCmds.add("else");
		createStopShellCmds.add("    echo kill $PID");
		createStopShellCmds.add("    kill $PID");
		createStopShellCmds.add("fi");
		FileUtil.newFile(stopShell);
		FileUtil.writeLines(createStopShellCmds, stopShell, "UTF-8");
		LinuxHelper.runCmd("chmod +x " + stopShell);
	}

	private static void initConfig() {
		String path = projectAbsolutePath + "/config/autodeploy-config.properties";
		if (!FileUtil.exist(path)) {
			return;
		}
		List<String> readLines = FileUtil.readLines(path, "UTF-8");
		for (String line : readLines) {
			if (line.startsWith("#") || line.startsWith("end")) {
				continue;
			}
			String[] split = line.split("=");
			configs.put(split[0], split[1]);
		}

	}

}
